package cn.wangxl.group.rpc.stub;

import cn.wangxl.group.rpc.discover.LocalConfigServiceInfoDiscoverer;
import cn.wangxl.group.rpc.discover.ServiceInfoDiscoverer;
import cn.wangxl.group.rpc.handler.ClientStubInvocationHandler;
import cn.wangxl.group.rpc.netclient.BioNetClient;
import cn.wangxl.group.rpc.netclient.NetClient;
import cn.wangxl.group.rpc.protocol.JavaMessageProtocol;
import cn.wangxl.group.rpc.protocol.JsonMessageProtocol;
import cn.wangxl.group.rpc.protocol.MessageProtocol;
import cn.wangxl.group.rpc.protocol.Protocol;

import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Deacription ClientStubProxyFactory
 * @Author 20112128
 * @Date 2020/9/18 10:41
 **/
public class ClientStubProxyFactory {

    private ServiceInfoDiscoverer sid;

    private Map<String, MessageProtocol> supportMessageProtocols;

    private NetClient netClient;

    private Map<Class<?> ,Object> objectCache = new HashMap<>();

    public ClientStubProxyFactory() {
        init();
    }

    public ClientStubProxyFactory(ServiceInfoDiscoverer sid,NetClient netClient) {
        this();
        this.sid = sid;
        this.netClient = netClient;
    }

    void init(){
        System.out.println("加载消息协议处理器");

        supportMessageProtocols = new ConcurrentHashMap<>();

        supportMessageProtocols.put(Protocol.JSON.getName(),new JsonMessageProtocol());
        supportMessageProtocols.put(Protocol.JAVA.getName(),new JavaMessageProtocol());

    }

    public <T> T getProxy(Class<T> clazz){

        Object proxy = objectCache.get(clazz);
        if(proxy!=null){
            return (T)proxy;
        }

        // 创建代理类执行器
        ClientStubInvocationHandler clientStubInvocationHandler
                = new ClientStubInvocationHandler(netClient,
                sid,
                supportMessageProtocols,
                clazz
                );
        // 创建代理类
        proxy =
                Proxy.newProxyInstance(clazz.getClassLoader(),
                new Class[]{clazz},
                clientStubInvocationHandler
        );

        objectCache.put(clazz,proxy);

        return (T)proxy;
    }


    public void setSid(ServiceInfoDiscoverer sid) {
        this.sid = sid;
    }

    public void setSupportMessageProtocols(Map<String, MessageProtocol> supportMessageProtocols) {
        this.supportMessageProtocols = supportMessageProtocols;
    }


    public void setNetClient(NetClient netClient) {
        this.netClient = netClient;
    }
}
